package com.estock.platform.task;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.estock.common.model.security.Stock;
import com.estock.common.util.CommonUtil;
import com.estock.platform.manager.CacheManager;
import com.estock.platform.task.support.ESJob;
import com.estock.platform.task.support.YahooCsvDownload;

/**
 * We control cron task scheduler manually, instead of annotation
 * 
 * @author richard
 *
 */
@Component
public class YahooCsvDataLoader extends ESJob {
	/** Logger */
	private static Logger logger = Logger.getLogger(YahooCsvDataLoader.class);
	
	private Long request_interval = 0L;
	private boolean useMultiThreading = true;
	
	private static final int BULK_SIZE = 3000;
	private ExecutorService executor;
	
	int bulkSize = 0;
	int downloadNum = 0;
	
	@Override
    public void executeJob() {
        // start executing task job
		List<Stock> stocks = getAllStocksShldLoad();
		
		if (!useMultiThreading) {
			// no multi-threading, fuck yahoo!
			for (Stock stock : stocks) {
				new YahooCsvDownload(stock).run();
				if (request_interval != null) {
					try {
						Thread.sleep(request_interval);
					} catch (InterruptedException e) {
					}
				}
			}
		} else {
			List<Stock> bulkStocks = new ArrayList<Stock>(stocks.size());
			while (downloadNum < stocks.size()) {
//				executor = Executors.newFixedThreadPool(Math.min(stocks.size(), BULK_SIZE), new HandlerThreadFactory());
				executor = Executors.newCachedThreadPool(new HandlerThreadFactory());
				
				while (bulkSize < BULK_SIZE && downloadNum < stocks.size()) {
					bulkStocks.add(stocks.get(downloadNum));
					bulkSize++;
					downloadNum++;
				}
				
				try {
					logger.info("start new thread of getting csv data from yahoo.");
					for (Stock stock : bulkStocks) {
			    		executor.execute(new Thread(new YahooCsvDownload(stock)));
			    	}
				} catch (Exception e) {
					// continue
				}
				
				bulkSize = 0;
				bulkStocks.clear();
				
				executor.shutdown();
				try {
					while (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
					}
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				
				
				// wait 1 second between every request.
				try {
					System.out.println("Sleeping 1 second for another request.");
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
		logger.info("Successfully teminated yahoo csv data loader task.");
		System.out.println("Successfully teminated yahoo csv data loader task.");
		
		System.gc();
    }
	
	protected List<Stock> getAllStocksShldLoad() {
		return CacheManager.getInstance().getStocksShldUpdateTrans();
	}
	
	public static void main(String[] args) {
		CommonUtil.isUnitTest = true;
		YahooCsvDataLoader instance = null;
		// generate urls for reference
		new DownloadUrlGenerator().executeJob();
		
		instance = new YahooCsvDataLoader();
//		instance = new YahooCsvDataLoader() {
//			protected List<Stock> getAllStocksShldLoad() {
//				List<Stock> stocks = new ArrayList<Stock>();
//				stocks.add(new Stock("000625", 2, ""));
//				//stocks.add(new Stock("002024", 2, ""));
//				return stocks;
//			}
//		};
		
		if (args != null && args.length != 0) {
			try {
				instance.request_interval = Long.valueOf(args[0]);
			} catch (Exception e) {
				throw new RuntimeException("Please input right thread sleeping milliseconds!");
			}
			
			if (StringUtils.equalsIgnoreCase("false", args[1])) {
				instance.useMultiThreading = false;
			}
		}
		
		instance.executeJob();
//		CommonUtil.setUnitTest(false); // will set false before thread be executed.
	}

}
